import React, { memo, useState, useEffect, useRef } from 'react'
import type { FC, ReactNode } from 'react'
import { useNavigate } from 'react-router-dom'
import classNames from 'classnames'

import fetchData from '../../request'
import ListCodeView from '../../components/ListCodeView'
import ShareCardList from '../../components/ShareCardList'
import { useMyDispatch } from '../../store'
import { setCodeAll, setID, setExit } from '../../store/modules/codeall'
import {
  setIsOpen,
  setPassword,
  setTitle,
  setCurrentTime,
  setLabel
} from '../../store/modules/create'

import {
  setMdContent,
  setCodeUrl,
  setTheme,
  setShareOrEdit,
  setFocusLanguage,
  setCopyCode
} from '../../store/modules/success'

import styles from './index.module.scss'
import '../../styles/iconfont.css'

interface IProps {
  children?: ReactNode
}

interface codeAllType {
  label: string
  key: string
  language: string
  codeSlice: string
}

interface CodeItem {
  title: string
  isOpen: boolean
  currentTime: string
  label: string[]
  codeAll: codeAllType[]
  codeUrl: string
  endTime: string
  id: string
  theme: string
  mdContent: string
  password: string
  handleDelete: (id: string) => void
  handleOpenChange: (id: string) => void
}

const CodeItemComponent: FC<CodeItem> = ({
  title,
  isOpen,
  currentTime,
  label,
  codeAll,
  id,
  endTime,
  password,
  codeUrl,
  mdContent,
  theme,
  handleDelete,
  handleOpenChange
}) => {
  const [isShowShareCard, setIsShowShareCard] = useState(false)
  const [isopen, setisopen] = useState(isOpen)
  const navigate = useNavigate()
  const dispatch = useMyDispatch()
  const [mb1, setMB1] = useState(false)
  const [mb2, setMB2] = useState(false)
  const [mb3, setMB3] = useState(false)
  const [moreSettings, setMoreSettings] = useState(false)
  const [passwordInput, setPasswordInput] = useState('')
  const [passNotEmpty, setPassNotEmpty] = useState(password)
  const pointRef = useRef<HTMLDivElement | null>(null)
  const moreRef = useRef<HTMLDivElement | null>(null)
  let timeCode: NodeJS.Timeout | null = null

  const handleMouseEnter = (event: React.MouseEvent<HTMLSpanElement>) => {
    event.stopPropagation()
    if (timeCode) clearTimeout(timeCode)
    setIsShowShareCard(true)
  }

  const handleMouseLeave = () => {
    timeCode = setTimeout(() => {
      setIsShowShareCard(false)
    }, 1000)
  }

  useEffect(() => {
    // 组件卸载时清除定时器
    return () => {
      if (timeCode) {
        clearTimeout(timeCode)
      }
    }
  }, [timeCode])

  const handleIsOpen = (open: boolean) => {
    setisopen(open)
  }

  const dispatchAll = async () => {
    dispatch(setCodeAll(codeAll))
    dispatch(setFocusLanguage(codeAll[0].language))
    dispatch(setCopyCode(codeAll[0].codeSlice))
    dispatch(setID(id))
    dispatch(setIsOpen(isopen))
    dispatch(setPassword(passNotEmpty))
    dispatch(setTitle(title))
    dispatch(setTheme(theme))
    dispatch(setCurrentTime(currentTime))
    // dispatch(setEndTime(endTime))
    dispatch(setLabel(label))
    dispatch(setMdContent(mdContent))
    dispatch(setCodeUrl(codeUrl))
    dispatch(setShareOrEdit(true))
    dispatch(setExit(true))
  }
  const jumpDetail = async () => {
    await dispatchAll()
    navigate('/success')
  }

  const handleConfirmClick = async () => {
    await fetchData('/update', { id, isOpen: true }, 'POST')
    setMB1(false)
    setisopen(true)
    handleOpenChange(id)
  }

  const handleConfirmClick2 = async () => {
    if (passwordInput.length > 8 || passwordInput.length < 4) {
      alert('密码长度应该是4-8位')
      return
    }
    setMB2(false)
    setisopen(false)
    dispatch(setPassword(passwordInput))
    setPassNotEmpty(passwordInput)
    handleOpenChange(id)
    setPasswordInput('')
    await fetchData(
      '/update',
      { id, isOpen: false, password: passwordInput },
      'POST'
    )
  }

  const handleClickOutside = (event: MouseEvent) => {
    if (
      pointRef.current &&
      moreRef.current &&
      !pointRef.current.contains(event.target as Node) &&
      !moreRef.current.contains(event.target as Node)
    ) {
      setMoreSettings(false)
    }
  }

  useEffect(() => {
    if (moreSettings) document.addEventListener('mousedown', handleClickOutside)
    else document.removeEventListener('mousedown', handleClickOutside)

    return () => {
      document.removeEventListener('mousedown', handleClickOutside)
    }
  }, [moreSettings])

  return (
    <div
      key={id}
      className={classNames(styles.codeItem)}
      onClick={() => {
        jumpDetail()
      }}
    >
      <div className={classNames(styles.title)}>
        <span>{title}</span>
        <span
          className={classNames(
            'iconfont',
            isopen ? 'icon-jiesuosuo' : 'icon-suo',
            styles.suo
          )}
        ></span>
      </div>
      <div className={classNames(styles.startTime)}>
        <span>创建于{currentTime}</span>
        <span
          className={classNames('iconfont icon-sangediandian', styles.points)}
          onClick={(e) => {
            e.stopPropagation()
            setMoreSettings(true)
          }}
          ref={pointRef}
        ></span>
      </div>
      <div className={classNames(styles.codeView)}>
        <ListCodeView code={codeAll[0].codeSlice} />
      </div>
      <div className={classNames(styles.footer)}>
        <span>{isopen ? '公开' : '加密'}</span>
        <span>{label.length > 0 ? label[0] : '未选择标签'}</span>
        <span
          className={classNames('iconfont icon-fenxiang1', styles.fenxiang)}
          onClick={(e) => {
            e.stopPropagation()
          }}
          onMouseEnter={handleMouseEnter}
          onMouseLeave={handleMouseLeave}
        >
          分享
        </span>
        <div
          className={classNames(
            styles.shareCard,
            isShowShareCard ? '' : styles.notActive
          )}
          onClick={(e) => {
            e.stopPropagation()
          }}
          onMouseEnter={handleMouseEnter}
          onMouseLeave={handleMouseLeave}
        >
          <ShareCardList
            handleIsOpen={handleIsOpen}
            id={id}
            endTime={endTime}
            isOpen={isopen}
            password={passNotEmpty}
          />
        </div>
      </div>

      {/* 设置内容 ---------------------------------------------------------------------------------*/}
      <div
        className={classNames(
          styles.pointContent,
          moreSettings && styles.pointContentActive
        )}
        ref={moreRef}
        onClick={(e) => {
          e.stopPropagation()
        }}
      >
        <div
          className={styles.pointItem}
          onClick={() => {
            if (isopen) {
              setMB2(true)
            } else {
              setMB1(true)
            }
          }}
        >
          <div
            className={classNames(
              'iconfont',
              isopen ? 'icon-suo' : 'icon-jiesuosuo',
              styles.icon
            )}
          ></div>
          <div className={styles.text}>{isopen ? '加密' : '取消加密'}</div>
        </div>
        <div
          className={styles.pointItem}
          onClick={() => {
            dispatchAll()
            navigate('/create')
          }}
        >
          <div
            className={classNames('iconfont', 'icon-bianji', styles.icon)}
          ></div>
          <div className={styles.text}>编辑</div>
        </div>
        <div
          className={styles.pointItem}
          onClick={() => {
            setMB3(true)
          }}
        >
          <div
            className={classNames('iconfont', 'icon-shanchu', styles.icon)}
          ></div>
          <div className={styles.text}>删除</div>
        </div>
      </div>

      {/* 三个蒙版------------------------------------------------------------------------- */}
      <div
        className={classNames(styles.mengban1, mb1 && styles.mengban1Active)}
        onClick={(e) => {
          e.stopPropagation()
        }}
      >
        <div className={classNames(styles.menban1content)}>
          <div
            className={classNames('iconfont', 'icon-jiesuosuo', styles.jiesuo)}
          ></div>
          <span>取消加密</span>
          <div className={styles.opencode}>取消加密，代码将会公开</div>
          <div className={classNames(styles.button2)}>
            <div
              className={styles.cancel}
              onClick={() => {
                setMB1(false)
              }}
            >
              取消
            </div>
            <div className={styles.confirm} onClick={handleConfirmClick}>
              确定
            </div>
          </div>
        </div>
      </div>

      <div
        className={classNames(styles.mengban2, mb2 && styles.mengban2Active)}
        onClick={(e) => {
          e.stopPropagation()
        }}
      >
        <div className={styles.mengban2content}>
          <div className={classNames('iconfont', 'icon-suo', styles.suo)}></div>
          <span>加密</span>
          <div className={styles.inputD}>
            <input
              type="password"
              value={passwordInput}
              onChange={(e) => {
                setPasswordInput(e.target.value)
              }}
            />
          </div>
          <div className={classNames(styles.button2)}>
            <div
              className={styles.cancel}
              onClick={() => {
                setMB2(false)
              }}
            >
              取消
            </div>
            <div className={styles.confirm} onClick={handleConfirmClick2}>
              确定
            </div>
          </div>
        </div>
      </div>

      <div
        className={classNames(styles.mengban3, mb3 && styles.mengban3Active)}
        onClick={(e) => {
          e.stopPropagation()
        }}
      >
        <div className={styles.mengban3content}>
          <div
            className={classNames('iconfont', 'icon-jinggao', styles.jinggao)}
          ></div>
          <span>是否确认删除? 不可找回</span>
          <div
            className={classNames(styles.button2)}
            onClick={() => {
              setMB3(false)
            }}
          >
            <div className={styles.cancel}>取消</div>
            <div
              className={styles.confirm}
              onClick={async () => {
                handleDelete(id)
                await fetchData('/delete', { id }, 'POST')
              }}
            >
              确定
            </div>
          </div>
        </div>
      </div>
    </div>
  )
}

const CodeList: FC<IProps> = () => {
  const [codeMessage, setCodeMessage] = useState<CodeItem[]>([])
  const [codeList, setcodeList] = useState<CodeItem[]>([])
  const [searchKey, setSearchKey] = useState('')
  const [shareRange, setShareRange] = useState('')
  const [codeLanguage, setCodeLanguage] = useState('')

  // 原来useEffect是可以存在很多个的???!!!
  useEffect(() => {
    const fetchMessage = async () => {
      try {
        const response = await fetchData('/get')
        const data = await response.json()
        setCodeMessage(data)
        setcodeList(data)
      } catch (error) {
        console.error(error)
      }
    }
    fetchMessage()
  }, [])

  useEffect(() => {
    handleCodeList(shareRange, codeLanguage)
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, [codeMessage, shareRange, codeLanguage])

  const handleCodeList = (shareRange: string, codeLanguage: string) => {
    const searchInObject = (obj: unknown): boolean => {
      if (typeof obj === 'object' && obj !== null) {
        if (Array.isArray(obj)) {
          // 如果是数组，递归检查每个元素
          return obj.some(searchInObject)
        } else {
          // 如果是对象，递归检查每个属性值
          return Object.values(obj).some(searchInObject)
        }
      } else if (typeof obj === 'string') {
        // 如果是字符串，检查是否包含目标字符串
        return obj.includes(searchKey)
      }
      return false
    }

    let temList = codeMessage.filter((obj) => {
      return searchInObject(obj)
    })

    if (temList.length === 0) {
      setcodeList(temList)
      return
    }
    if (shareRange === 'Private') {
      temList = temList.filter((item: CodeItem) => item.isOpen === false)
    } else if (shareRange === 'Open') {
      temList = temList.filter((item: CodeItem) => item.isOpen === true)
    }

    if (codeLanguage !== '' && codeLanguage !== 'all') {
      if (codeLanguage === '未选择标签') {
        temList = temList.filter((item: CodeItem) => {
          return item.label.length === 0
        })
      } else
        temList = temList.filter((item: CodeItem) => {
          return item.label.includes(codeLanguage)
        })
    }
    setcodeList(temList)
  }

  const handleDelete = (id: string) => {
    setCodeMessage(codeList.filter((item: CodeItem) => item.id !== id))
  }

  const handleOpenChange = (id: string) => {
    const itemList = codeMessage.map((item: CodeItem) => {
      if (item.id === id) {
        return { ...item, isOpen: !item.isOpen }
      }
      return item
    })
    console.log(codeMessage)
    setCodeMessage(itemList)
  }

  return (
    <div className={classNames(styles.container)}>
      <div className={classNames(styles.searchKey)}>
        <input
          type="text"
          placeholder="输入关键词搜索"
          onChange={(e) => {
            setSearchKey(e.target.value)
          }}
        />
        <div
          className={classNames('iconfont icon-sousuo', styles.sousuo)}
          onClick={() => {
            handleCodeList(shareRange, codeLanguage)
          }}
        ></div>
      </div>
      <div className={classNames(styles.searchOpt)}>
        <select
          name="searchAround"
          id=""
          onChange={(e) => {
            setShareRange(e.target.value)
          }}
          defaultValue="fenxiang"
        >
          <option value="fenxiang" disabled hidden>
            分享范围
          </option>
          <option value="Open">公开</option>
          <option value="Private">加密</option>
          <option value="all">所有范围</option>
        </select>
        <select
          name="searchLanguage"
          id=""
          onChange={(e) => {
            setCodeLanguage(e.target.value)
          }}
          defaultValue="biancheng"
        >
          <option value="biancheng" disabled hidden>
            编程语言
          </option>
          <option value="JavaScript">JavaScript</option>
          <option value="Java">Java</option>
          <option value="Python">Python</option>
          <option value="C++">C++</option>
          <option value="C">C</option>
          <option value="C#">C#</option>
          <option value="HTML">HTML</option>
          <option value="CSS">CSS</option>
          <option value="SCSS">SCSS</option>
          <option value="MarkDown">MarkDown</option>
          <option value="GO">GO</option>
          <option value="JSON">JSON</option>
          <option value="未选择标签">未知标签</option>
          <option value="all">所有语言</option>
        </select>
      </div>
      <div className={classNames(styles.codeContent)}>
        {codeList.length > 0 ? (
          codeList.map((item: CodeItem) => (
            <CodeItemComponent
              {...item}
              key={item.id}
              handleDelete={handleDelete}
              handleOpenChange={handleOpenChange}
            />
          ))
        ) : (
          <div>没有数据</div>
        )}
      </div>
    </div>
  )
}

export default memo(CodeList)
